// SPDX-FileCopyrightText: Adam Evyčędo
//
// SPDX-License-Identifier: GPL-3.0-or-later

package xyz.apiote.bimba.czwek.search.ui.results

import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.launch
import xyz.apiote.bimba.czwek.data.exceptions.BimbaException
import xyz.apiote.bimba.czwek.data.traffic.TrafficRepository
import xyz.apiote.bimba.czwek.repo.FeedInfo.Companion.ID_TRANSITOUS
import xyz.apiote.bimba.czwek.repo.Position
import xyz.apiote.bimba.czwek.repo.Queryable

// TODO sort results

class ResultsViewModel : ViewModel() {
	private val mutableResults = MutableStateFlow(listOf<Queryable>())
	val results: StateFlow<List<Queryable>> = mutableResults
	private val finishedSearching = MutableStateFlow(false)
	val finished: StateFlow<Boolean> = finishedSearching

	var startedSearching: Boolean = false
		private set

	private val errors: MutableSet<BimbaException> = mutableSetOf()

	fun consumeErrors(): List<BimbaException> {
		val errors = this.errors.map { it }
		this.errors.clear()
		return errors
	}

	fun query(q: String, context: Context) {
		viewModelScope.launch(Dispatchers.IO) {
			TrafficRepository()
				.queryQueryables(q, context)
				.onStart { startedSearching = true }
				.onCompletion { finishedSearching.value = true }
				.collect { flowResult ->
					when (flowResult) {
						is BimbaException -> {
							errors.add(flowResult)
						}

						is Queryable -> {
							mutableResults.value = mutableResults.value.plus(flowResult)//.sortedBy {  }
						}
					}
				}
		}
	}

	fun geocode(q: String, context: Context) {
		val repository = TrafficRepository()
		viewModelScope.launch(Dispatchers.IO) {
			val places = repository.queryPlaces(q, context)
			val stops = repository.queryQueryables(q, context, listOf(ID_TRANSITOUS))
			listOf(places, stops)
				.merge()
				.onStart { startedSearching = true }
				.onCompletion { finishedSearching.value = true }
				.collect { flowResult ->
					when (flowResult) {
						is BimbaException -> {
							errors.add(flowResult)
						}

						is Queryable -> {
							mutableResults.value = mutableResults.value.plus(flowResult)//.sortedBy {  }
						}
					}
				}
		}
	}

	fun locate(p: Position, context: Context) {
		startedSearching = false
		finishedSearching.value = false
		mutableResults.value = emptyList()
		viewModelScope.launch(Dispatchers.IO) {
			TrafficRepository()
				.locateQueryables(p, context)
				.onStart {
					startedSearching = true
				}
				.onCompletion { finishedSearching.value = true }
				.collect { flowResult ->
					when (flowResult) {
						is BimbaException -> {
							errors.add(flowResult)
						}

						is Queryable -> {
							mutableResults.value = mutableResults.value
								.plus(flowResult)
								.toSet()
								.sortedBy {
									it.location()
										?.distanceTo(p) /* TODO these are both queryables and locatables, they *must* have a position*/
								}
								.take(12)
						}
					}
				}
		}
	}
}